package com.ccp.dev.workflow.service;

import com.ccp.dev.core.basic.base.BaseService;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.util.StringPool;
import com.ccp.dev.core.util.StringUtil;
import com.ccp.dev.core.util.log.SysAuditThreadLocalHolder;
import com.ccp.dev.system.model.SysUser;
import com.ccp.dev.system.service.SysOrgService;
import com.ccp.dev.system.service.SysUserService;
import com.ccp.dev.workflow.dao.BpmNodeUserDao;
import com.ccp.dev.workflow.dao.BpmUserConditionDao;
import com.ccp.dev.workflow.model.BpmNodeUser;
import com.ccp.dev.workflow.model.BpmUserCondition;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ClassDescribe:节点下的人员的配置规则   Service类
 * @author :jiayueqiao
 * Date: 2019-05-15
 * Since:1
 */
@Service
public class BpmUserConditionService extends BaseService<BpmUserCondition> {


    @Resource
    private BpmUserConditionDao dao;
    @Resource
    private BpmNodeUserDao bpmNodeUserDao;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private SysOrgService sysOrgService;


    /**
     * 保存人员设置和规则设置。
     * @param bpmUserCondition 条件
     * @param users 设置的人员
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveConditionAndUser(BpmUserCondition bpmUserCondition,String users){
        String conditionId;
        JSONArray jarray = JSONArray.fromObject(users);
        if(StringUtil.isNotEmpty(bpmUserCondition.getId())){
            conditionId = bpmUserCondition.getId();
            dao.update(bpmUserCondition);
            //根据条件ID删除组合条件。
            bpmNodeUserDao.delByConditionId(conditionId);
        }
        else{
            conditionId = UUIDUtils.getUUIDFor32();
            bpmUserCondition.setId(conditionId);
            dao.add(bpmUserCondition);
        }
        for(Object obj : jarray){
            JSONObject jobject = (JSONObject)obj;
            String cmpIds=jobject.getString("cmpIds");

            String nodeUserId=UUIDUtils.getUUIDFor32();
            BpmNodeUser nodeUser = new BpmNodeUser();
            nodeUser.setNodeUserId(nodeUserId);

            String assignType= jobject.getString("assignType");
            nodeUser.setAssignType(assignType);

            nodeUser.setCmpIds(cmpIds);
            nodeUser.setCmpNames(jobject.getString("cmpNames"));
            Short extractUser = 0;
            if(jobject.has("extractUser")){
                extractUser = Short.parseShort(jobject.getString("extractUser"));
            }
            nodeUser.setExtractUser(extractUser);
            nodeUser.setCompType(Short.parseShort(jobject.getString("compType")));
            nodeUser.setConditionId(conditionId);

            bpmNodeUserDao.add(nodeUser);
        }
    }

    /**
     * 根据节点设置id查询
     * @param setId 节点设置id
     * @return list
     */
    @Transactional(rollbackFor = Exception.class)
    public List<BpmUserCondition> queryBySetId(String setId){
        //2020-03-21 jyq添加，解决用户调换组织后，人员设置显示不正确问题
        //查询流程定义节点人员设置
        List<BpmUserCondition> bpmUserConditionList =  dao.queryBySetId(setId);
        //条件id
        String conditionId;
        //条件显示，例如"用户:张三[子租户],六六[管理组织]"
        String conditionShow;
        for(BpmUserCondition bpmUserCondition:bpmUserConditionList){
            conditionId = bpmUserCondition.getId();
            conditionShow = bpmUserCondition.getConditionShow();
            //查询用户类型的设置
            List<BpmNodeUser> bpmNodeUserList = bpmNodeUserDao.queryByConditionIdAndType(conditionId,BpmNodeUser.ASSIGN_TYPE_USER);
            for(BpmNodeUser bpmNodeUser:bpmNodeUserList){
                //用户id，例如"86a13dc153ea425d9a29b753077cc86c,7b0de3f58022444b85ea6d28847f0b91"
                String cmpIds =bpmNodeUser.getCmpIds();
                //用户名称，例如"张三[子租户],六六[管理组织]"
                String cmpNames = bpmNodeUser.getCmpNames();
                String[] cmpIdArray = cmpIds.split(",");
                StringBuilder newCmpNames = new StringBuilder("");
                for(int i=0;i<cmpIdArray.length;i++){
                    String userId = cmpIdArray[i];
                    SysUser sysUser = sysUserService.getOneById(userId);
                    String orgName = sysOrgService.getOrgByUserId(userId).getOrgName();
                    newCmpNames.append(sysUser.getFullName()+"["+orgName+"],");
                }
                newCmpNames.deleteCharAt(newCmpNames.length()-1);
                //若不相同，则更新数据库bpm_node_user表
                if(!cmpNames.equals(newCmpNames.toString())){
                    bpmNodeUser.setCmpNames(newCmpNames.toString());
                    bpmNodeUserDao.update(bpmNodeUser);
                    conditionShow = conditionShow.replace(cmpNames,newCmpNames.toString());
                }
            }
            //若不同，则更新数据库bpm_user_condition表
            if(!bpmUserCondition.getConditionShow().equals(conditionShow)){
                bpmUserCondition.setConditionShow(conditionShow);
                dao.update(bpmUserCondition);
            }
        }
        return bpmUserConditionList;
    }

    /**
     * 删除用户条件设置
     * @param conditionId 条件id
     */
    @Transactional(rollbackFor = Exception.class)
    public void delByConditionId(String conditionId){
        dao.delById(conditionId);
        bpmNodeUserDao.delByConditionId(conditionId);
    }

    /**
     * 删除用户条件设置
     * @param conditionIds 条件id
     */
    @Transactional(rollbackFor = Exception.class)
    public void delByConditionIds(String conditionIds){
        if (conditionIds.contains(StringPool.COMMA)) {
            String[] conditionIdArr = conditionIds.split(",");
            for (String conditionId : conditionIdArr) {
                delByConditionId(conditionId);
            }
        }else {
            delByConditionId(conditionIds);
        }

    }

    /**
     * 查询用户设置
     * @param map （其中conditionType =0,执行人员;1,抄送人员）;
     * @return list
     */
    public List<BpmUserCondition> queryByProcDefIdOrParentId(Map<String, Object> map) {
        return dao.queryByProcDefIdOrParentId(map);
    }

    /**
     * 通过流程定义ID获得抄送用户设置条件
     * @param procDefId 流程定义id
     * @param nodeId 节点id
     * @return list
     */
    public List<BpmUserCondition> queryByProcDefIdAndNodeId(String procDefId, String nodeId) {
        return dao.queryByProcDefIdAndNodeId(procDefId, nodeId);
    }

    /**
     * 通过流程定义ID和节点ID获取触发新流程的发起人
     * @param procDefId 流程定义id
     * @param nodeId 节点id
     */
    public List<BpmUserCondition> getTriggerNewFlowStartUserConditions(String procDefId, String nodeId) {
        if (!nodeId.startsWith(BpmUserCondition.TRIGGER_NEWFLOW_STARTUSER_NODE_PRDFIX)) {
            nodeId = BpmUserCondition.TRIGGER_NEWFLOW_STARTUSER_NODE_PRDFIX + nodeId;
        }

        return dao.queryByProcDefIdAndNodeId(procDefId, nodeId);
    }

    /**
     * 通过流程定义ID和节点ID，获取消息节点的内部消息接收人
     * @param procDefId 流程定义id
     * @param nodeId 节点id
     * @return list
     */
    public List<BpmUserCondition> getReceiverInnerConditions(String procDefId, String nodeId) {
        Map<String,Object> params = new HashMap<>(3);
        params.put("procDefId", procDefId);
        params.put("nodeId", nodeId);
        params.put("conditionType", BpmUserCondition.CONDITION_TYPE_MSG_INNER_RECEIVER);
        return dao.queryByProcDefIdAndNodeIdAndType(params);
    }

    /**
     * 获取流程设置的抄送人员
     * @param procDefId 流程定义id
     * @param parentProcDefId 父流程定义id
     */
    public List<BpmUserCondition> queryCcByProcDefId(String procDefId, String parentProcDefId) {
        Map<String,Object> params = new HashMap<>(3);
        params.put("procDefId", procDefId);
        params.put("conditionType", BpmUserCondition.CONDITION_TYPE_COPYUSER);
        if (StringUtil.isNotEmpty(parentProcDefId)) {
            params.put("parentProcDefId", parentProcDefId);
        }
        return dao.queryByProcDefIdOrParentId(params);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateSn(String conditionId, int sn) {
        dao.updateSn(conditionId,sn);
    }
}
